package myoar

import akka.NotUsed
import akka.actor.ActorSystem
import akka.stream._
import akka.stream.scaladsl._
import com.typesafe.scalalogging.StrictLogging

object Stream extends StrictLogging {

  implicit val system = ActorSystem("etc")
  implicit val materializer = ActorMaterializer(
    ActorMaterializerSettings(system)
      .withInputBuffer(
        initialSize = 1,
        maxSize = 1))

  import scala.concurrent.duration._

  type In0 = Myo.Angles
  type In1 = Myo.Pose
  type Out = Drone.WantedState

  val orientationSource =
    Source.queue[In0](1, OverflowStrategy.dropHead)
  val poseSource =
    Source.queue[In1](1, OverflowStrategy.dropHead)

  val g = RunnableGraph.fromGraph(
    GraphDSL.create(orientationSource, poseSource)((_, _)) {
      implicit builder => (inOrientation, inGesture) =>
        import GraphDSL.Implicits._

        val out = Sink.foreach{ x:Drone.WantedState =>
          logger.info(x.toString);
          x.run(Drone.drone)
        }

        def replay[T] = Flow[T].expand(Iterator.continually(_))

        val zipToWantedState =
          builder.add(
            ZipWith(
              (angles:In0,pose:In1)
              => Myo.zip(pose = pose, curAngles = angles):Out ))

        val bucketSize = 1

        val headDropper = Flow[Out]
          .buffer(1,OverflowStrategy.dropHead)

        def throttle[T](i:Int) = Flow[T]
          .throttle(1, i.seconds, bucketSize, ThrottleMode.Shaping)
        //.withAttributes(Attributes.inputBuffer(initial = 1, max = 1))

        //val logger = Flow.map(i => {println("Logging " + i); i})

        /*
        inOrientation ~> replay ~> throttleFaster ~> logger ~> zipToWantedState.in0
        inGesture ~> replay ~> zipToWantedState.in1
        zipToWantedState.out ~> headDropper ~> throttle ~> out
        */

       //val merge = builder.add(Merge[Int](2))
       //val bcast = builder.add(Broadcast[Int](2))
       inOrientation ~> replay[In0] ~> zipToWantedState.in0
       inGesture ~> replay[In1] ~> zipToWantedState.in1
       zipToWantedState.out ~> out

       ClosedShape

    })

  val (orientationQ, poseQ) = g.run

}

/*
 For console:

 import myoar._
 import Stream._; import Myo._
 val a1 = Angles(1, 1, 1)
 val a2 = Angles(0, 0, 0)
 val p1 = Poses.REST
 val p2 = Poses.DOUBLE_TAP
 val p3 = Poses.FIST

 */
